package main

import (
	"go.uber.org/zap"
	"learngo/errorhandling/filelistserver/common"
	"log"
	"net/http"
	"os"
)

//将func HandleError(writer http.ResponseWriter,request *http.Request) error 定义
//出一个匿名函数，名为handleErrorFunc， 以便在当前类可以使用它
type handleErrorFunc func(writer http.ResponseWriter, request *http.Request) error

type userError interface {
	error
	Message() string
}

//包装下errorCallBackFunc，返回一个func
func wrapperError(errHandle handleErrorFunc) func(w http.ResponseWriter, r *http.Request){
	logger, _ := zap.NewProduction()
	return func(writer http.ResponseWriter, request *http.Request){
		// 处理panic的异常，不至于程序中断
		defer func(){
			if r := recover(); r != nil {
				log.Printf("Panic: %v", r)
				http.Error(writer,
					http.StatusText(http.StatusInternalServerError),
					http.StatusInternalServerError)
			}
		}()

		err := errHandle(writer,request) //执行common.HandleError
		if err !=nil {
			logger.Warn(err.Error())

			if userErr,ok := err.(userError); ok {
				http.Error(writer, userErr.Message(), http.StatusBadRequest)
				return
			}
			stattusCode := http.StatusOK
			switch  {
			case os.IsNotExist(err):
				stattusCode = http.StatusNotFound
			case os.IsPermission(err):
				stattusCode = http.StatusForbidden
			default:
				stattusCode = http.StatusInternalServerError
			}
			http.Error(writer,http.StatusText(stattusCode),stattusCode)
		}
	}
}

//http://localhost:9999/list/fib.txt
func main() {
	http.HandleFunc("/", wrapperError(common.HandleError))
	err := http.ListenAndServe(":9999",nil)
	if err !=nil {
		panic("unkown error")
	}
}

